package com.manager.user.utils;

import com.manager.commons.log.LogFactory;
import com.manager.commons.utils.FileUtils;
import com.manager.user.module.entity.GenFiles;
import net.coobird.thumbnailator.Thumbnails;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.slf4j.Logger;

import javax.imageio.*;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.List;

public class MediaInfoUtils {
    public static final String ROOT_PATH = "/user/files";
    public static final String THUMBNAIL_PATH = "/thumbnail";

    protected static Logger logger = LogFactory.getLogger(FileUtils.class);
    protected static final Map<String, String> imageExt = new LinkedHashMap<String, String>() {
        {
            put("png", "");
            put("jpg", "");
            put("gif", "");
            put("image", "");
            put("webp", "");
            put("bmp", "");
        }
    };
    protected static final Map<String, String> videoExt = new LinkedHashMap<String, String>() {
        {
            put("mp4", "");
            put("avi", "");
            put("mkv", "");
            put("wmv", "");
            put("mov", "");
        }
    };
    protected static final Map<String, String> audioExt = new LinkedHashMap<String, String>() {
        {
            put("mp3", "");
            put("wav", "");
            put("aac", "");
            put("flac", "");
            put("ogg", "");
            put("m4a", "");
            put("wma", "");
            put("amr", "");
        }
    };
    protected static final Map<String, String> documentExt = new LinkedHashMap<String, String>() {
        {
            put("txt", "");
            put("doc", "");
            put("docx", "");
            put("xls", "");
            put("xlsx", "");
            put("ppt", "");
            put("pptx", "");
            put("pdf", "");
            put("rtf", "");
            put("wps", "");
            put("odt", "");
            put("ods", "");
            put("odp", "");
        }
    };

    protected static final Map<String, String> archiveExt = new LinkedHashMap<String, String>() {
        {
            put("zip", "");
            put("rar", "");
            put("7z", "");
            put("tar", "");
            put("gz", "");
            put("war", "");
        }
    };

    /**
     * 判断文件是否为文档格式
     *
     * @param extFile 后缀名
     * @return 如果是文档格式返回true，否则返回false
     */
    public static boolean isDocument(String extFile) {
        if (extFile == null || extFile.isEmpty()) {
            return false;
        }

        return documentExt.containsKey(extFile);
    }

    /**
     * 判断文件是否为压缩包格式
     *
     * @param extFile 文件名
     * @return 如果是压缩包格式返回true，否则返回false
     */
    public static boolean isArchive(String extFile) {
        if (extFile == null || extFile.isEmpty()) {
            return false;
        }
        return archiveExt.containsKey(extFile);
    }

    public static String iaArchiveOrDocumnet(String extFile) {
        if (extFile == null || extFile.isEmpty()) {
            return extFile;
        }
        if (documentExt.containsKey(extFile)) {
            return "document";
        } else if (archiveExt.containsKey(extFile)) {
            return "rar";
        } else {
            return extFile;
        }
    }


    public static String getImageResolution(File imageFile) throws Exception {
        try (ImageInputStream iis = ImageIO.createImageInputStream(imageFile)) {
            Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);
            if (!readers.hasNext()) {
                throw new Exception("不支持的图片格式");
            }

            ImageReader reader = readers.next();
            reader.setInput(iis, false, false);
            int width = reader.getWidth(0);
            int height = reader.getHeight(0);
            reader.dispose();
            logger.info(width + "x" + height);
            return width + "x" + height;
        }
    }


    // 判断文件类型的辅助方法
    public static boolean isImageFile(String ext) {
        // 根据扩展名判断（实际项目建议结合 MIME 类型）
        return imageExt.containsKey(ext);
    }

    public static boolean isVideoFile(String ext) {
        return videoExt.containsKey(ext);
    }

    public static boolean isAudioFile(String ext) {
        return audioExt.containsKey(ext);
    }

    /**
     * 生成图片缩略图（使用 Thumbnails 库）
     *
     * @param originalImagePath 原始图片路径
     * @param thumbnailPath     缩略图保存路径
     * @param targetWidth       目标宽度（像素）
     * @param targetHeight      目标高度（像素）
     * @throws IOException 处理图片过程中可能的 IO 异常
     */
    public static void ImageThumbnail(String originalImagePath, String thumbnailPath,
                                      int targetWidth, int targetHeight) throws Exception {
        Thumbnails.of(originalImagePath)
                .size(targetWidth, targetHeight)
                .keepAspectRatio(true)  // 保持宽高比
                .outputQuality(0.8)     // 输出质量（0.0-1.0）
                .toFile(thumbnailPath);
    }

    public static void ImageThumbnail(String file, String outImage) throws Exception {
//        Thumbnails.of(path)
//                .size(300, 300)
//                .keepAspectRatio(true)  // 保持宽高比
//                .outputQuality(0.5)     // 输出质量（0.0-1.0）
//                .toFile(outImage);
        // 核心优化点：
        try {
            logger.debug(outImage);
            OutputStream out = Files.newOutputStream(Paths.get(outImage));
            Thumbnails.of(file)
                    // 按比例缩放（避免拉伸变形）
                    .size(200, 200)
                    // 仅当原图尺寸大于目标尺寸时才缩放（小图不放大）
                    .keepAspectRatio(true)
                    // 优化内存：不加载完整原图，直接处理
                    .outputQuality(0.6)  // 质量参数（0.0-1.0，平衡质量和文件大小）
                    // 选择高效格式（WebP比JPG/PNG更优）
                    .outputFormat("webp")
                    // 流式输出，减少中间缓存
                    .toOutputStream(out);
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }


    /**
     * 获取视频的第一帧并保存为图片
     * path 完整路径
     * saveThumbPath 保存路径
     *
     * @throws Exception 如果处理视频或保存图片失败
     */
    public static void VideoThumbnail(GenFiles files, String path, String saveThumbPath) throws Exception {
        try {
            FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(path);
            grabber.start();
            int width = grabber.getImageWidth();
            int height = grabber.getImageHeight();
            long duration = grabber.getLengthInTime() / 1000; // 转为毫秒
            files.setResolution(width + " x " + height);
            files.setDuration(formatDuration(duration));
            Frame frame;
            // 读取第一帧
            while ((frame = grabber.grabImage()) != null) {
                Java2DFrameConverter converter = new Java2DFrameConverter();
                BufferedImage image = converter.convert(frame);
                // 调整尺寸压缩
                BufferedImage resizedImage = resizeImage(image, 300, 300);
                // 保存图片
                compressAndSave(resizedImage, saveThumbPath, 0.5f);
                break;
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * 获取音频文件的时长（毫秒）
     *
     * @param path 音频文件路径
     * @return 时长（毫秒）
     * @throws Exception 如果读取失败
     */
    public static String getAudioDuration(String path) throws Exception {
        try (FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(path)) {
            grabber.start();
            long duration = grabber.getLengthInTime() / 1000; // 转为毫秒
            return formatDuration(duration);
        }
    }


    /**
     * 将毫秒转换为 HH:MM:SS 格式
     *
     * @param duration 时长（毫秒）
     * @return 格式化的时间字符串
     */
    public static String formatDuration(long duration) {
        long seconds = duration / 1000;
        long hours = seconds / 3600;
        seconds %= 3600;
        long minutes = seconds / 60;
        seconds %= 60;

        if (hours > 0) {
            return String.format("%02d:%02d:%02d", hours, minutes, seconds);
        } else {
            return String.format("%02d:%02d", minutes, seconds);
        }
    }

    /**
     * 压缩并保存图片
     *
     * @param image      原始图片
     * @param outputPath 输出路径
     * @param quality    压缩质量（0.0-1.0，仅适用于支持的格式）
     * @throws IOException 如果保存失败
     */
    public static void compressAndSave(BufferedImage image, String outputPath, float quality) throws IOException {
        String formatName = "jpg";
        // 验证质量参数
        if (quality < 0 || quality > 1) {
            throw new IllegalArgumentException("质量参数必须在 0.0 到 1.0 之间");
        }

        try (OutputStream os = Files.newOutputStream(Paths.get(outputPath));
             ImageOutputStream ios = ImageIO.createImageOutputStream(os)) {

            // 获取图片写入器
            Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName);
            if (!writers.hasNext()) {
                throw new IllegalStateException("找不到支持的图片写入器: " + formatName);
            }

            ImageWriter writer = writers.next();
            writer.setOutput(ios);

            // 获取写入参数
            ImageWriteParam param = writer.getDefaultWriteParam();

            // 如果支持压缩质量且是 JPG 格式，则设置压缩质量
            if (param.canWriteCompressed() && QUALITY_SUPPORTED_FORMATS.contains(formatName.toLowerCase())) {
                param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
                param.setCompressionQuality(quality);
            }

            // 写入图片
            writer.write(null, new IIOImage(image, null, null), param);
            writer.dispose();
        }
    }

    /**
     * 按指定大小压缩图片（保持宽高比）
     *
     * @param originalImage 原始图片
     * @param maxWidth      最大宽度
     * @param maxHeight     最大高度
     * @return 压缩后的图片
     */
    public static BufferedImage resizeImage(BufferedImage originalImage, int maxWidth, int maxHeight) {
        int originalWidth = originalImage.getWidth();
        int originalHeight = originalImage.getHeight();

        // 计算宽高比
        double ratio = (double) originalWidth / originalHeight;

        // 计算新尺寸（保持宽高比）
        int newWidth, newHeight;
        if (originalWidth > maxWidth || originalHeight > maxHeight) {
            if (ratio > 1) {
                newWidth = maxWidth;
                newHeight = (int) (newWidth / ratio);
            } else {
                newHeight = maxHeight;
                newWidth = (int) (newHeight * ratio);
            }
        } else {
            return originalImage; // 不需要调整大小
        }

        // 创建新图片并绘制
        BufferedImage resizedImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = resizedImage.createGraphics();

        try {
            // 设置高质量缩放
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
            g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            // 绘制图片
            g.drawImage(originalImage, 0, 0, newWidth, newHeight, null);
        } finally {
            g.dispose();
        }

        return resizedImage;
    }

    // 支持压缩质量的格式
    private static final List<String> QUALITY_SUPPORTED_FORMATS = Arrays.asList("jpg", "jpeg");
}